import requests
from typing import Optional, Dict, Union, Tuple, List
from config.settings import get_config
from base.base_page import BasePage


class HttpRequestPage(BasePage):
    def __init__(self, driver, device_type, logger=None):
        super().__init__(driver, device_type, logger=logger)
        self.driver = driver
        self.config = get_config(device_type)

    def http_request(
            self,
            direction: str,
            url: str,
            method: str = 'GET',
            headers: Optional[Dict[str, str]] = None,
            body: Optional[Union[Dict, str, bytes]] = None,
            apikey: Optional[str] = None,
            expected_status: Optional[int] = None,
            expected_response: Optional[Union[Dict, str]] = None,
            ** kwargs
    ) -> Tuple[int, Union[Dict, str]]:
        """
        增强版HTTP请求方法

        :param direction: 请求方向，"请求方"或"服务方"
        :param method: 请求方法，默认GET
        :param headers: 自定义请求头
        :param body: 请求体内容
        :param expected_status: 预期状态码
        :param expected_response: 预期响应内容
        :param kwargs: 其他requests参数
        """
        # 构建完整URL
        full_url = url

        # 处理API密钥
        final_apikey = apikey
        # if direction == "请求方" and not final_apikey:
        #     error = "请求方必须提供有效的API密钥"
        #     self.logger.error(error)
        #     raise ValueError(error)

        # 设置默认超时
        kwargs.setdefault("timeout", 10)

        # 记录请求信息
        # self.logger.info(f"▷▷▷ 发起 {direction} {method} 请求")
        if body:
            self.logger.debug(f"请求体: {body}")

        try:
            # 发送请求
            response = self._send_request(
                method=method.upper(),
                url=full_url,
                headers=headers,
                body=body,
                apikey=final_apikey,
                direction=direction,
            ** kwargs
            )

            # 处理响应
            status_code, response_data = self._process_response(response)

            # 执行断言验证
            self._validate_response(expected_status, expected_response, status_code, response_data)

            return status_code, response_data

        except requests.RequestException as e:
            error = f"请求异常: {str(e)}"
            self.logger.error(error, exc_info=True)
            return 500, error
        except AssertionError as ae:
            self.logger.error(f"断言失败: {str(ae)}")
            raise  # 向上抛出断言异常
        except Exception as e:
            error = f"未知错误: {str(e)}"
            self.logger.error(error, exc_info=True)
            return 500, error

    def _send_request(self, method, url, headers, body, apikey, direction, ** kwargs):
        """封装请求发送逻辑"""
        base_headers = {'Content-Type': 'application/json', 'Connection': 'close'}
        final_headers = {**base_headers, ** (headers or {})}

        # 添加API密钥
        if direction == "请求方":
            final_headers['apikey'] = apikey

        # 处理不同内容类型的请求体
        req_kwargs = {'headers': final_headers, ** kwargs}
        if body is not None:
            content_type = final_headers.get('Content-Type', '').lower()
            req_kwargs['json' if 'json' in content_type and isinstance(body, dict) else 'data'] = body

        return requests.request(method=method, url=url, ** req_kwargs)

    def _process_response(self, response):
        """处理响应解析"""
        try:
            response_data = response.json()
        except requests.JSONDecodeError:
            response_data = response.text

        status_code = response.status_code

        # self.logger.info(f"◁◁◁ 收到响应 [状态码 {status_code}]")
        # self.logger.info(f"响应内容: {response_data}")
        return status_code, response_data

    # def _validate_response(self, expected_status, expected_response, actual_status, actual_response):
    #     """执行响应验证"""
    #     try:
    #         if expected_status is not None:
    #             assert expected_status == actual_status, \
    #                 f"状态码验证失败: 预期 {expected_status} ≠ 实际 {actual_status}"
    #             self.logger.info(f"状态码验证通过: {actual_status}")
    #     except AssertionError as e:
    #         self.logger.error(e)
    #
    #     try:
    #         if expected_response is not None:
    #             assert expected_response in actual_response, \
    #                 f"响应内容验证失败\n预期: {expected_response}\n实际: {actual_response}"
    #             self.logger.info("响应内容验证通过")
    #     except AssertionError as e:
    #         self.logger.error(e)

    def _validate_response(self, expected_status, expected_response, actual_status, actual_response):
        """增强类型支持的响应验证"""
        # 状态码验证
        status_check = True
        if expected_status is not None:
            try:
                assert expected_status == actual_status, \
                    f"状态码不匹配 | 预期: {expected_status}({type(expected_status)}) ≠ 实际: {actual_status}({type(actual_status)})"
                self.logger.info(f"状态码验证通过: {actual_status}")
            except AssertionError as e:
                status_check = False
                self.logger.error(str(e))

        # 响应内容验证
        content_check = True
        if expected_response is not None:
            try:
                # 处理数字类型比较
                if isinstance(expected_response, (int, float)):
                    assert actual_response == expected_response, \
                        f"数值不匹配 | 预期: {expected_response}({type(expected_response)}) ≠ 实际: {actual_response}({type(actual_response)})"
                # 处理字符串/字典包含关系
                elif isinstance(expected_response, (dict, list)):
                    assert expected_response.items() <= actual_response.items() if isinstance(actual_response,
                                                                                              dict) else False, \
                        f"字典包含不匹配 | 预期字段: {expected_response} 不在实际响应中"
                else:
                    assert str(expected_response) in str(actual_response), \
                        f"内容不匹配 | 预期内容未找到: {expected_response}"

                self.logger.info("响应内容验证通过")
            except AssertionError as e:
                content_check = False
                self.logger.error(str(e))

        return status_check and content_check